package server;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Date;

import service.ServerService;
import utility.CONST;

public class UDPServer {

	// socket object
	private DatagramSocket serverSocket = null;
	private DatagramPacket serverPacket = null;
	private boolean isRunning = true;
	private Thread serverThread = null;
	private byte[] request = null;

	public UDPServer() {
		try {
			this.serverSocket = new DatagramSocket(CONST.DEFAULT_PORT);
			this.start();
		} catch (IOException e) {
			serverSocket.close();
			e.printStackTrace();
			System.out.println(e.getMessage());
		}
	}

	private void start() {
		System.out.println("Server start at " + new Date());
		serverThread = new Thread(new Runnable() {
			public void run() {
				request = new byte[1024];
				serverPacket = new DatagramPacket(request, request.length);
				while (isRunning) {
					try {
						serverSocket.receive(serverPacket);
						System.out.println("Server received!!");
				
						ServerService serverService = new ServerService(serverPacket);
								
						Thread t = new Thread(serverService);
						t.start();
					} catch (IOException e) {
						e.printStackTrace();
						System.out.println(e.getMessage());
					}
				}
				System.out.println("Server end at " + new Date());
			}
		});
		serverThread.start();
	}

	/*class UDPServerService implements Runnable {
		private DatagramSocket _serverSocket;
		private DatagramPacket _serverPacket;
		private int receivePort;
		private InetAddress receiveInetAddress;
		private byte[] receiveData;
		private boolean isAlive = true;

		public UDPServerService(DatagramSocket _serverSocket,
				DatagramPacket _serverPacket) {
			this._serverSocket = _serverSocket;
			this._serverPacket = _serverPacket;
			this.receivePort = _serverPacket.getPort();
			this.receiveInetAddress = _serverPacket.getAddress();
			this.receiveData = _serverPacket.getData();
			
			G5File.printPacket(this._serverPacket);
		}

		public void stop() {
			this.isAlive = false;
		}
		
		public DatagramPacket get_serverPacket() {
			return _serverPacket;
		}

		@Override
		public void run() {
			System.out.println(this.receiveData.length);
			System.out.println(this.receiveInetAddress.getHostAddress());
			System.out.println(this.receivePort);
			
			G5Packet g5Packet = null; //

			byte[] request = null; // request byte array
			byte[] sendByte = null; // send data byte array

			int type;

			try {
				request = new byte[1024];

				request = this.receiveData;
				g5Packet = (G5Packet) G5File.byteArrayToObj(request);

				type = g5Packet.getType();

				switch (type) {
				case G5Packet.FIND: // looking for request
					String fileName,
					chunkDir,
					checkSum,
					fullPath;

					fileName = g5Packet.getFileName(); // file name of file will
														// looking for
					checkSum = g5Packet.getCheckSum(); // check sum of file will
														// looking for
					chunkDir = G5File.DEFAULT_CHUNK_DIR; // default chunk dir
					System.out.println("This is a looking for " + fileName
							+ " request");

					fullPath = findFile(fileName, chunkDir, checkSum);

					if (G5File.compareString(fullPath, "") == false) { // have
																		// file
						System.out.println(this.receiveData.length);
						System.out.println(this.receiveInetAddress.getHostAddress());
						System.out.println(this.receivePort);
						
						// packet store response
						G5Packet responseFindPacket = new G5Packet(fullPath,
								G5Packet.RESPONSE_FIND);
						byte[] responseFindFileData = G5File.objToByte(responseFindPacket);
						
						this._serverPacket = G5Service.getUnicastPacket(responseFindFileData, this.receiveInetAddress, this.receivePort);

						this._serverSocket.send(this._serverPacket);
						
						System.out.println("Server response find packet successful");
					}
					break;
				case G5Packet.RESPONSE_FIND: // get file request
					/*
					 * String option; File fFound; G5Packet responseGetPacket =
					 * new
					 * 
					 * option = g5Packet.getOption(); fFound = new File(option);
					 

					break;
				}
			} catch (Exception e) {
				e.getStackTrace();
				System.out.println(e.getMessage());
			}
		}*/

		/*private String findFile(String fileName, String dir, String checkSum) {
			File fFound = null;
			File fDir = null;
			String _checkSum = "";
			String fullPath = "";
			try {
				// looking for find in dir
				fDir = new File(dir);
				for (File file : fDir.listFiles()) {
					if (file.getName().matches(fileName)) {
						fFound = file;
						break;
					}
				}

				// if exists file
				if (fFound != null) {
					_checkSum = G5File.getFileHashCode_SHA1(fFound);
					// compare check sum
					if (G5File.compareString(_checkSum, checkSum)) {
						fullPath = fFound.getPath();
					}
				}
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
				System.out.println(e.getMessage());
			} catch (IOException e) {
				e.printStackTrace();
				System.out.println(e.getMessage());
			}
			return fullPath;
		}
	}*/
}
